package com.zdxlz.desensitize;

import com.zdxlz.desensitize.core.BaseDesensitizeAspect;
import com.zdxlz.desensitize.core.IDesensitizeRuleService;
import com.zdxlz.desensitize.core.IDesensitizeService;
import com.zdxlz.desensitize.core.RequiredDesensitize;
import com.zdxlz.desensitize.util.DesensitizeUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Objects;

/**
 * 脱敏统一拦截器
 */
@Aspect
public class DesensitizeAspect extends BaseDesensitizeAspect {
    private final IDesensitizeRuleService ruleService;

    public DesensitizeAspect(IDesensitizeRuleService ruleService,IDesensitizeService desensitizeService, DesensitizeUtil desensitizeUtil) {
        this.ruleService = ruleService;
        setDesensitizeService(desensitizeService);
        setDesensitizeUtil(desensitizeUtil);
    }

    /**
     * 根据实际路径进行调整
     */
    @Pointcut("@annotation(com.zdxlz.desensitize.core.RequiredDesensitize)")
    public void execute() {}

    @Around("execute()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        Object obj = point.proceed();
        // 不处理空和基本数据类型和String类型
        if (null == obj || isPrimitive(obj.getClass()) || !ruleService.allowDesensitize(obj)) {
            return obj;
        }
        try {
            // 获取注解
            MethodSignature signature = (MethodSignature) point.getSignature();
            Method method = signature.getMethod();
            RequiredDesensitize anno = method.getAnnotation(RequiredDesensitize.class);
            // 获取request
            HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
            if(anno.simpleMode()) {
                return sensitiveFormat(obj,request);
            }else {
                return sensitiveFormat(obj,anno,request);
            }
        }catch (Exception e) {
            e.printStackTrace();
        }
        return obj;
    }
}

